﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Henke.DevUI.Utils.Specifications;

namespace Henke.DevUI.Policy.Common
{
    public class PolicyTargetRepo:IPolicyTargetRepo
    { 
        private readonly IList<IAssembly> _targetAssemblies=new List<IAssembly>();

        /// <summary>
        /// Initializes a new instance of the <see cref="PolicyTargetRepo"/> class.
        /// </summary>
        /// <param name="targetAssembly">The target assembly.</param>
        public PolicyTargetRepo(IAssembly targetAssembly)
        {
            _targetAssemblies.Add(targetAssembly);
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="PolicyTargetRepo"/> class.
        /// </summary>
        /// <param name="targetAssemblies">The target assemblies.</param>
        public PolicyTargetRepo(IEnumerable<IAssembly> targetAssemblies)
        {
            foreach (var targetAssembly in targetAssemblies)
            {
                _targetAssemblies.Add(targetAssembly);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PolicyTargetRepo"/> class.
        /// Creates a simple Targetassembly
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        public PolicyTargetRepo(Assembly assembly)
            : this(new TargetAssembly(assembly))
        {            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PolicyTargetRepo"/> class.
        /// </summary>
        /// <param name="targetAssemblies">The target assemblies.</param>
        public PolicyTargetRepo(IEnumerable<Assembly> targetAssemblies)
        {
            foreach (var targetAssembly in targetAssemblies)
            {
                _targetAssemblies.Add(new TargetAssembly(targetAssembly));
            }
        }

        public  IEnumerable<IPolicyTarget> All()
        {
            var assemblies = new List<Type>();
            foreach (var targetAssembly in _targetAssemblies)
            {
                assemblies.AddRange(targetAssembly.AllTypes());
            }

            return assemblies.Select(type => new PolicyTarget(type)).Cast<IPolicyTarget>().ToList();
        }

        public  IEnumerable<IPolicyTarget> All(ISpecification<IPolicyTarget> criteria)
        {
            return All().Where(criteria.IsSatisfiedBy);
        }
    }
}
